
package principal;


import componentes.Cliente;
import componentes.Configuracao;
import componentes.Linux;
import componentes.Servidor;
import excessoes.ServicoDeBloqueioJaAtivo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Hashtable;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import threads.CarregaConfigs;
import threads.Handler;
import threads.ServicoDeBloqueio;

        
/**
 *
 * @author Wagner Tavares
 */
public class Main extends Thread{
    private static ServicoDeBloqueio servicoDeBloqueio;
    private static Hashtable<String,Cliente> clientes = new Hashtable<String,Cliente>();
    private static Servidor servidor = new Servidor();
    private Thread handler;
    public static Configuracao config = new Configuracao();
    private static File backup = new File(Linux.pathProg+File.separator+"dados/dados.dat");
    private static Logger logger = Logger.getLogger(Main.class.getName());
    
    public static void main(String [] args){
        launchLog();
        desserializar();
        config.run();
        if(config.getPortaAuth()!=0 && config.getPortaSquid()!=0 && config.getTimeOut() != 0 && !config.getLlogin().contains(" ")){
            CarregaConfigs loaderConfs = new CarregaConfigs(config, servidor, clientes);
            loaderConfs.run();
            Main main = new Main();
            main.start();
        }else{
            logger.logp(Level.SEVERE, "Main", "main()", "Arquivo de configuração inválido. Não foi possível iniciar");
        }
    }
    @Override
    public void run(){
        try {
            Main.servicoDeBloqueioStart();
            //handler = new Handler(clientes,(Runnable)consultaClientes,(Runnable)consultaServidor,servicoDeBloqueio);
            handler = new Handler(config, servidor, clientes, servicoDeBloqueio);
            handler.start();
        } catch (ServicoDeBloqueioJaAtivo ex) {
            Logger.getLogger(Main.class.getName()).logp(Level.WARNING, Main.class.getName(),"run()",ex.getMessage());
        }
    }
    public static void servicoDeBloqueioStart() throws ServicoDeBloqueioJaAtivo{
        if(servicoDeBloqueio==null || !servicoDeBloqueio.isAlive()){
            servicoDeBloqueio = new ServicoDeBloqueio(config,clientes);
            servicoDeBloqueio.start();
        } else 
            throw new ServicoDeBloqueioJaAtivo();
    }
    public static void servicoDeBloqueioStop(){
        servicoDeBloqueio.stopMe();
    }
    public static void servicoDeBloqueioRestart(){
        servicoDeBloqueioStop();
        try {
            servicoDeBloqueioStart();
        } catch (ServicoDeBloqueioJaAtivo ex) {
            Logger.getLogger(Main.class.getName()).logp(Level.WARNING, Main.class.getName(),"run()",ex.getMessage());
        }
    }
    public static void serializar(){
        try {
            File dadosPath;
            if(!(dadosPath = new File(Linux.pathProg+File.separator+"dados")).isDirectory())
                dadosPath.mkdir();
            FileOutputStream fos = new FileOutputStream(backup);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(servidor);
            oos.flush();
            oos.writeObject(clientes);
            oos.flush();
            oos.close();
            fos.close();
        } catch (FileNotFoundException e) {
            logger.logp(Level.WARNING,"Main","serializar()","Arquivo não encontrado");
        } catch (IOException e) {
            logger.logp(Level.SEVERE,"Main","serializar()","Erro ao acessar o arquivo "+backup, e);
        }
    }
    public static void desserializar(){
        try{
            FileInputStream fis = new FileInputStream(backup);
            ObjectInputStream ois = new ObjectInputStream(fis);
            servidor = (Servidor)ois.readObject();
            clientes = (Hashtable<String,Cliente>)ois.readObject();
            ois.close();
            fis.close();
        } catch(ClassNotFoundException e){
            logger.logp(Level.SEVERE,"Main","desserializar()","Classe não encontrada", e);
        } catch(FileNotFoundException e){
            logger.logp(Level.WARNING,"Main","desserializar()","Arquivo não encontrado");
        } catch(InvalidClassException e){
            logger.logp(Level.SEVERE,"Main","desserializar()","Erro ao acessar o arquivo "+backup);
        } catch(IOException e){
            logger.logp(Level.SEVERE,"Main","desserializar()","Erro ao acessar o arquivo "+backup);
        }
    }
    public static void launchLog(){
        try {
            logger.setLevel(Level.ALL);
            File logPath = new File(Linux.pathLog);
            if(!logPath.isDirectory())
                logPath.mkdir();
            String nome = "auth", nomeInc = "auth";
            File log;
            for(int i = 1;(log=new File(logPath.getAbsolutePath()+File.separator+nomeInc+".log")).isFile();i++)
                nomeInc=nome+i;
            //FileHandler h = new FileHandler(logPath.getAbsolutePath()+File.separator+"autenticacao.log"); // Nome do arquivo de log
            FileHandler h = new FileHandler(log.getAbsolutePath()); // Nome do arquivo de log
            h.setFormatter(new SimpleFormatter()); // Formatação do log
            logger.addHandler(h);
            logger.setUseParentHandlers(true);
        } catch (IOException ex) {
            logger.log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
    }
}
